﻿using System.Collections.Concurrent;
using TaskPollingWebApi.Models;
using TaskPollingWebApi.Services;

namespace TaskPollingWebApi.ServicesImpl
{
    public class TaskPollingService : ITaskPollingService
    {
        // 任务状态存储
        private readonly ConcurrentDictionary<int, TaskStatusInfo> _taskStatuses = new();

        // 轮询控制
        private bool _isRunning;
        private bool _isPollingInProgress;
        private Timer _timer;
        private readonly SemaphoreSlim _semaphore = new(1, 1); // 确保同一时间只有一个轮询周期执行

        // 轮询配置
        private readonly int _pollingIntervalSeconds = 5; // 轮询间隔
        private readonly int _batchSize = 5; // 每批处理的任务数量
        private readonly int _taskTimeoutSeconds = 1; // 单个任务超时时间

        // 轮询统计信息
        private int _completedCycles;
        private DateTime? _lastCycleStartTime;
        private DateTime? _lastCycleEndTime;
        private TimeSpan? _lastCycleDuration;

        public TaskPollingService()
        {
            // 初始化100个任务
            for (int i = 1; i <= 100; i++)
            {
                _taskStatuses.TryAdd(i, new TaskStatusInfo
                {
                    TaskId = i,
                    Status = "Pending",
                    LastCheckedTime = null,
                    CheckCount = 0,
                    IsCompleted = false
                });
            }
        }

        public void Start()
        {
            if (_isRunning)
            {
                return;
            }

            _isRunning = true;
            _completedCycles = 1;

            // 立即开始第一次轮询，之后根据间隔执行
            _timer = new Timer(OnTimerElapsed, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(-1));

            Console.WriteLine("轮询服务已启动");
        }

        public void Stop()
        {
            if (!_isRunning)
            {
                return;
            }

            _isRunning = false;
            _timer?.Change(Timeout.Infinite, Timeout.Infinite);
            _timer?.Dispose();
            Console.WriteLine("轮询服务已停止");
        }

        public List<TaskStatusInfo> GetAllTasks()
        {
            return _taskStatuses.Values.OrderBy(t => t.TaskId).ToList();
        }

        public TaskStatusInfo GetTaskById(int id)
        {
            _taskStatuses.TryGetValue(id, out var task);
            return task;
        }

        public PollingStatus GetPollingStatus()
        {
            return new PollingStatus
            {
                IsRunning = _isRunning,
                IsPollingInProgress = _isPollingInProgress,
                CompletedCycles = _completedCycles,
                TotalTasks = _taskStatuses.Count,
                LastCycleStartTime = _lastCycleStartTime,
                LastCycleEndTime = _lastCycleEndTime,
                LastCycleDuration = _lastCycleDuration
            };
        }

        private void OnTimerElapsed(object? state)
        {
            Console.WriteLine($"========尝试第{_completedCycles}次轮询");
            // 如果当前正在轮询，或者服务已停止，则直接返回
            if (!_isRunning || !_semaphore.WaitAsync(0).GetAwaiter().GetResult())
            {
                Console.WriteLine($"================第{_completedCycles}次轮询中，跳过");
                ScheduleNextPoll();
                return;
            }

            Console.WriteLine($"==================================开始第{_completedCycles}次轮询");

            try
            {
                // 标记当前正在轮询
                _isPollingInProgress = true;
                _lastCycleStartTime = DateTime.Now;

                // 执行轮询周期
                ExecutePollingCycle().GetAwaiter().GetResult();

                _completedCycles++;
                _lastCycleEndTime = DateTime.Now;
                _lastCycleDuration = _lastCycleEndTime - _lastCycleStartTime;
            }
            catch (Exception ex)
            {
                // 记录轮询过程中的异常
                Console.WriteLine($"轮询周期执行出错: {ex.Message}");
            }
            finally
            {
                // 重置轮询状态
                _isPollingInProgress = false;
                _semaphore.Release();

                // 安排下一次轮询
                ScheduleNextPoll();
            }
        }

        /// <summary>
        /// 安排下一次轮询
        /// </summary>
        private void ScheduleNextPoll()
        {
            if (_isRunning && _timer != null)
            {
                // 计算下一次轮询的时间（从上一次轮询结束后开始计算间隔）
                _timer.Change(TimeSpan.FromSeconds(_pollingIntervalSeconds), TimeSpan.FromMilliseconds(-1));
            }
        }

        /// <summary>
        /// 执行一个完整的轮询周期
        /// </summary>
        private async Task ExecutePollingCycle()
        {
            // 获取所有未完成的任务
            var activeTasks = _taskStatuses.Values
                //.Where(t => !t.IsCompleted)
                .Select(t => t.TaskId)
                .ToList();

            if (!activeTasks.Any())
            {
                return;
            }

            // 分批处理任务，每批10个
            foreach (var batch in activeTasks.Batch(_batchSize))
            {
                // 并行处理当前批次的任务
                var tasks = batch.Select(taskId => CheckTaskStatusAsync(taskId));
                await Task.WhenAll(tasks);
            }
        }

        /// <summary>
        /// 检查单个任务的状态
        /// </summary>
        private async Task CheckTaskStatusAsync(int taskId)
        {
            Console.WriteLine($"=>{taskId}:");

            try
            {
                using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(_taskTimeoutSeconds));

                // 模拟查询任务状态（替换为实际的查询逻辑）
                var queryTask = QueryTaskStatusAsync(taskId, cts.Token);
                var completedTask = await Task.WhenAny(queryTask, Task.Delay(Timeout.Infinite, cts.Token));
                if (completedTask == queryTask)
                {
                    Console.WriteLine($"=>{taskId}:完成");
                    // 查询成功完成
                    if (_taskStatuses.TryGetValue(taskId, out var taskInfo))
                    {
                        var status = await queryTask;
                        taskInfo.Status = status;
                        taskInfo.LastCheckedTime = DateTime.Now;
                        taskInfo.CheckCount++;
                        taskInfo.IsCompleted = status == "Completed" || status == "Failed";
                    }
                }
                else
                {
                    Console.WriteLine($"=>{taskId}:超时");
                    // 超时
                    if (_taskStatuses.TryGetValue(taskId, out var taskInfo))
                    {
                        taskInfo.Status = "Timeout";
                        taskInfo.LastCheckedTime = DateTime.Now;
                        taskInfo.CheckCount++;
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理其他异常
                if (_taskStatuses.TryGetValue(taskId, out var taskInfo))
                {
                    taskInfo.Status = $"Error: {ex.Message}";
                    taskInfo.LastCheckedTime = DateTime.Now;
                    taskInfo.CheckCount++;
                }
            }
        }

        /// <summary>
        /// 模拟查询任务状态的方法（替换为实际实现）
        /// </summary>
        private async Task<string> QueryTaskStatusAsync(int taskId, CancellationToken cancellationToken)
        {
            // 模拟网络请求或耗时操作
            await Task.Delay(Random.Shared.Next(1, 2000), cancellationToken);

            // 随机模拟一些任务完成
            if (Random.Shared.NextDouble() < 0.1) // 10%的概率任务完成
            {
                return "Completed";
            }

            // 随机模拟一些任务失败
            if (Random.Shared.NextDouble() < 0.05) // 5%的概率任务失败
            {
                return "Failed";
            }

            // 大部分任务仍在运行
            return "Running";
        }
    }

    /// <summary>
    /// 任务状态信息
    /// </summary>
    public class TaskStatusInfo
    {
        public int TaskId { get; set; }
        public string Status { get; set; }
        public DateTime? LastCheckedTime { get; set; }
        public int CheckCount { get; set; }
        public bool IsCompleted { get; set; }
    }

    /// <summary>
    /// 批次处理扩展方法
    /// </summary>
    public static class BatchExtensions
    {
        public static IEnumerable<List<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
        {
            var batch = new List<T>(batchSize);
            foreach (var item in source)
            {
                batch.Add(item);
                if (batch.Count == batchSize)
                {
                    yield return batch;
                    batch = new List<T>(batchSize);
                }
            }
            if (batch.Count > 0)
            {
                yield return batch;
            }
        }
    }

}
